-- ==================================================== modified by v1ld ==================================================== ---------------------------------------------------------------------------------------------------------------------- --[[ scheme_type: generic author: Stohe modified_by: Alundaio --]] -- TODO: ---------------------------------------------------------------------------------------------------------------------- local M = {} local function get_vertex(npc) local rnd1,ang = math.random(100) if rnd1 < 43 then ang = math.random(50,60) elseif rnd1 < 58 then ang = math.random(160,200) else ang = math.random(300,310) end local dir = vector_rotate_y(npc:direction(),ang) return npc:vertex_in_direction(npc:level_vertex_id(),dir,math.random(4,6)) end local good_acts = { [xr_actions_id.animpoint_action + 1] = true } --------------------------------------------------------------------------------------------------------------------- --Evaluators ---------------------------------------------------------------------------------------------------------------------- --' Возвращает есть ли у нас контакт с другим сталкером class "evaluator_contact" (property_evaluator) function evaluator_contact:__init(name, storage) super (nil, name) self.a = storage end function evaluator_contact:evaluate() --utils_data.debug_write("eva_contact") if not (self.object:alive()) then return false end if self.a.meet_set ~= true then return false end -- if self.a.meet_only_at_path == true and not db.storage[self.object:id()].move_mgr:arrived_to_first_waypoint() then -- return false -- end if db.actor then if not db.actor:alive() then return false end self.a.meet_manager:update() if (db.storage[self.object:id()].victim_surrender == AC_ID) then return true end if xr_wounded.is_wounded(self.object) then return false end if self.object:best_enemy() ~= nil then return false end local state = state_mgr.get_state(self.object) if (state == "search_corpse" or state == "pickup_crouch") then return false end if (self.object:has_info("npcx_is_companion") or not get_object_story_id(self.object:id())) and not (self.object:is_talking()) then if (self.a.gtfo == true) then return true end if (db.actor:position():distance_to_sqr(self.object:position()) < 1.5) and not (good_acts[utils_obj.get_current_action_id(self.object)]) then self.a.dtimer = not self.a.dtimer and time_global() + 4000 or self.a.dtimer if (time_global() > self.a.dtimer) then self.a.dtimer = nil self.a.gtfo = true return true end end end local squad = self.object and get_object_squad(self.object) local commander = squad and squad:commander_id() ~= self.object:id() and level.object_by_id(squad:commander_id()) if (commander and state_mgr.get_state(commander) == "threat_na" and utils_obj.get_current_action_id(commander) == xr_actions_id.stohe_meet_base + 1) then if (self.object:see(db.actor) or db.actor:position():distance_to_sqr(self.object:position()) <= 225) then self.a.commander_threat = true return true end else self.a.commander_threat = nil end return self.a.meet_manager.current_distance ~= nil end return false end ---------------------------------------------------------------------------------------------------------------------- --Actions ---------------------------------------------------------------------------------------------------------------------- --' Приглашение к тороговле class "action_meet_wait" (action_base) function action_meet_wait:__init (npc_name,action_name, storage, char_ini) super (nil, action_name) self.char_ini = char_ini self.a = storage self.a.stage = 0 end function action_meet_wait:initialize() action_base.initialize(self) self.object:set_desired_position() self.object:set_desired_direction() state_mgr.set_state(self.object,"idle") end function action_meet_wait:execute () action_base.execute(self) local npc = self.object -- Move npc out of the way if player bumps into him if self.a.gtfo and self.a.can_gtfo == 'true' then if (npc:is_talking() or db.actor:position():distance_to_sqr(npc:position()) > 4) then utils_obj.send_to_nearest_accessible_vertex(npc,npc:level_vertex_id()) self.a.gtfo = nil self.a.vertex_id = nil self.a.stage = 0 return end if (self.a.stage == 0) then self.a.vertex_id = utils_obj.try_go_backward(npc,5,self.a.vertex_id) if (self.a.vertex_id) then npc:set_desired_direction() state_mgr.set_state(npc,"patrol") self.a.stage = 1 self.a.dtimer = time_global() + 4000 end elseif (self.a.stage == 1) then if (npc:level_vertex_id() == self.a.vertex_id or time_global() > self.a.dtimer) then self.a.gtfo = nil self.a.vertex_id = nil self.a.stage = 0 return end utils_obj.send_to_nearest_accessible_vertex(npc,self.a.vertex_id) end return elseif (self.a.commander_threat) then if (self.a.stage == 0) then if (utils_obj.squad_in_los(npc,db.actor)) then npc:set_desired_direction() state_mgr.set_state(npc,"rush") self.a.stage = 1 return else utils_obj.send_to_nearest_accessible_vertex(npc,npc:level_vertex_id(),"xr_meet") end elseif (self.a.stage == 1) then state_mgr.set_state(npc,"rush") local squad = get_object_squad(npc) local commander = squad:commander_id() and level.object_by_id(squad:commander_id()) self.a.vertex_id = get_vertex(commander) or npc:level_vertex_id() self.a.vertex_id = utils_obj.send_to_nearest_accessible_vertex(npc,self.a.vertex_id,"xr_meet") self.a.dtimer = time_global() + 3000 self.a.stage = 2 return elseif (self.a.stage == 2) then npc:set_desired_direction() state_mgr.set_state(npc,"rush") if (npc:level_vertex_id() == self.a.vertex_id) then self.a.stage = 0 else if (time_global() > self.a.dtimer) then self.a.stage = 0 end end return end npc:set_desired_direction() state_mgr.set_state(self.object, "threat_na", nil, nil, {look_object = db.actor}) return end self.a.meet_manager:update_state() end function action_meet_wait:finalize () action_base.finalize(self) self.a.stage = 0 self.a.gtfo = nil if (self.a.vertex_id) then db.used_level_vertex_ids[self.a.vertex_id] = nil self.a.vertex_id = nil end end -- Функционал --[[ -- звук на юзание CB --]] class "Cmeet_manager" function Cmeet_manager:__init(npc, storage) self.npc = npc self.a = storage self.startdialog = nil self.abuse_mode = nil self.trade_enable = nil self.use = nil self.allow_break = nil self.npc_is_camp_director = false self.curent_distance = nil -- nil - мит не активен, close - близко, far - далеко self.hello_passed = false -- Говорили ли мы привет self.bye_passed = false -- Говорили ли мы пока end function Cmeet_manager:update_state() local condlist = self.current_distance == "close" and self.a.close_anim or self.a.far_anim local state = condlist and xr_logic.pick_section_from_condlist(db.actor, self.npc, condlist) if (state and state ~= "nil" and state ~= "") then local victim_str = xr_logic.pick_section_from_condlist(db.actor, self.npc, self.current_distance == "close" and self.a.close_victim or self.a.far_victim) local victim = get_story_object(victim_str) state_mgr.set_state(self.npc, state, nil, nil, {look_object = victim}) end local snd = self.a.far_snd and xr_logic.pick_section_from_condlist(db.actor, self.npc, self.a.far_snd) if (snd and snd ~= "nil" and snd ~= "") then xr_sound.set_sound_play(self.npc:id(), snd) end end function Cmeet_manager:set_start_distance() if db.actor == nil then self.hello_passed = false self.bye_passed = false self.current_distance = nil return end if not self.npc:alive() then self.hello_passed = false self.bye_passed = false self.current_distance = nil return end -- Определение, в каком радиусе находимся local distance = self.npc:position():distance_to(db.actor:position()) local actor_visible = self.npc:see(db.actor) local is_object_far = actor_visible and distance <= tonumber(xr_logic.pick_section_from_condlist(db.actor, self.npc, self.a.far_distance) or 5) local is_object_close = (actor_visible and distance <= tonumber(xr_logic.pick_section_from_condlist(db.actor, self.npc, self.a.close_distance) or 3)) or self.npc:is_talking() if is_object_close == true then self.hello_passed = true self.current_distance = "close" elseif is_object_far == true then self.bye_passed = true self.current_distance = "far" elseif distance > self.a.reset_distance then self.hello_passed = false self.bye_passed = false self.current_distance = nil else self.current_distance = nil end end function Cmeet_manager:update() local tg = time_global() if (self.__stimer and tg < self.__stimer) then return end self.__stimer = tg + 500 -- Определение, в каком радиусе находимся local distance = self.npc:position():distance_to(db.actor:position()) local actor_visible = self.npc:see(db.actor) if actor_visible then --printf("%s check distance %s <= %s <= %s", self.npc:name(), distance, tonumber(xr_logic.pick_section_from_condlist(db.actor, self.npc, self.a.close_snd_distance)), tonumber(xr_logic.pick_section_from_condlist(db.actor, self.npc, self.a.far_snd_distance)) ) if distance <= tonumber(xr_logic.pick_section_from_condlist(db.actor, self.npc, self.a.close_snd_distance)) then -- Коллбек на приближение -- звук при приближении if self.hello_passed == false then self.hello_passed = true if not (state_mgr.is_npc_in_combat(self.npc)) then local snd = self.a.close_snd_hello and xr_logic.pick_section_from_condlist(db.actor, self.npc, self.a.close_snd_hello) if (snd and snd ~= "nil") then xr_sound.set_sound_play(self.npc:id(), snd) end end end elseif distance <= tonumber(xr_logic.pick_section_from_condlist(db.actor, self.npc, self.a.far_snd_distance)) then if self.hello_passed == true then -- Коллбек на отдаление -- звук при отдалении if self.bye_passed == false then self.bye_passed = true if not (state_mgr.is_npc_in_combat(self.npc)) then local snd = self.a.close_snd_bye and xr_logic.pick_section_from_condlist(db.actor, self.npc, self.a.close_snd_bye) if (snd and snd ~= "nil") then xr_sound.set_sound_play(self.npc:id(), snd) end end end end end end local is_object_far = actor_visible and distance <= tonumber(xr_logic.pick_section_from_condlist(db.actor, self.npc, self.a.far_distance) or 5) local is_object_close = (actor_visible and distance <= tonumber(xr_logic.pick_section_from_condlist(db.actor, self.npc, self.a.close_distance) or 3)) or (self.npc:is_talking() and self.a.meet_on_talking) --printf("!!! %s %s %s", self.npc:name(), tostring(is_object_far), tostring(is_object_close)) --printf("%s", xr_logic.pick_section_from_condlist(db.actor, self.npc, self.a.close_distance)) if is_object_close == true then if self.current_distance ~= "close" then self.current_distance = "close" end elseif is_object_far == true then self.current_distance = "far" elseif distance > self.a.reset_distance then -- ресет флажков при выходе в дальний радиус CB self.hello_passed = false self.bye_passed = false self.current_distance = nil else self.current_distance = nil end -- Можно или нет оборвать диалог local allow_break = xr_logic.pick_section_from_condlist(db.actor, self.npc, self.a.allow_break) if self.allow_break ~= (allow_break == "true") then self.allow_break = (allow_break == "true") end -- стартовый диалог local npc_id = self.npc:id() local script_dialog if (M[npc_id]) then if self.npc:name() == M[npc_id].name then script_dialog = M[npc_id].dialog_name else M[npc_id] = nil end end if self.a.meet_dialog ~= nil or script_dialog then local start_dialog = script_dialog or xr_logic.pick_section_from_condlist(db.actor, self.npc, self.a.meet_dialog) if (db.storage[self.npc:id()].victim_surrender == db.actor:id() and IsWounded(self.npc) and self.npc:relation(db.actor) >= game_object.enemy) then start_dialog = "dm_surrender_dialog" end if self.startdialog ~= start_dialog then self.startdialog = start_dialog -- printf("*DIALOGS %s* SET [%s]", self.npc:name(), tostring(start_dialog)) if start_dialog == nil or start_dialog == "nil" then -- восстановление начального -- printf("RESTORE") self.npc:restore_default_start_dialog() else -- установка нового -- printf("SET %s allow_break %s", start_dialog, tostring(self.allow_break)) self.npc:set_start_dialog(start_dialog) if self.npc:is_talking() then db.actor:run_talk_dialog(self.npc, not(self.allow_break)) end end end end local is_talking = self.npc:is_talking() local use = xr_logic.pick_section_from_condlist(db.actor, self.npc, self.a.use) -- Проверяем, играем ли мы что то в кампе if self.npc_is_camp_director == true then use = "false" end --utils_obj.debug_nearest(self.npc,"meet_manager.use=%s",use) --printf("%s self.use[%s] use [%s]", self.npc:name(), tostring(self.use), tostring(use)) --print_table(self.a.use) -- доступность юзания use = load_var(db.actor,"force_all_talk", false) and "true" or use if self.use ~= use then if use == "self" then if not is_talking and device().precache_frame < 1 then self.npc:enable_talk() --printf("SET allow_break %s", tostring(self.allow_break)) self.npc:allow_break_talk_dialog(self.allow_break) db.actor:run_talk_dialog(self.npc, not(self.allow_break)) end end if device().precache_frame < 1 then self.use = use end end local use_text = xr_logic.pick_section_from_condlist(db.actor, self.npc, self.a.use_text) if (use_text and use_text ~= "" and use_text ~= "nil") then self.npc:set_tip_text(use_text) elseif (self.npc:is_talk_enabled()) then self.npc:set_tip_text("character_use") else self.npc:set_tip_text("") end if (self.a.gtfo) then self.npc:allow_break_talk_dialog(false) else self.npc:allow_break_talk_dialog(self.allow_break) end --[[ if is_talking then db.actor:allow_break_talk_dialog(self.allow_break) end ]] -- Проверяем включать ли обижание на заюзывание local abuse = xr_logic.pick_section_from_condlist(db.actor, self.npc, self.a.abuse) if self.abuse_mode ~= abuse then if abuse == "true" then xr_abuse.enable_abuse(self.npc) else xr_abuse.disable_abuse(self.npc) end self.abuse_mode = abuse end -- доступность торговли if xr_wounded.is_wounded(self.npc) then self.trade_enable = false else local trade_enable = xr_logic.pick_section_from_condlist(db.actor, self.npc, self.a.trade_enable) --printf("npc [%s] self %s *** %s", self.npc:name(), tostring(self.trade_enable), tostring(trade_enable)) if self.trade_enable ~= trade_enable then if trade_enable == "true" then self.npc:enable_trade() else self.npc:disable_trade() end self.trade_enable = trade_enable end end end function notify_on_use(victim, who) --printf("NOTIFY [%s] used by [%s]", victim:name(), who:name()) -- Если мы мертвы - на юзание не реагировать if not victim:alive() then return end local storage = db.storage[victim:id()] if not (storage) then return end storage.after_first_meet = true local st = db.storage[victim:id()].meet if st == nil then return end local snd = xr_logic.pick_section_from_condlist(db.actor, victim, st.snd_on_use) if (snd and snd ~= "" and snd ~= "nil") then xr_sound.set_sound_play(victim:id(), snd) end local meet_manager = st.meet_manager if meet_manager.use == "false" and meet_manager.abuse_mode == "true" and game_relations.get_npcs_relation(victim, db.actor) == game_object.friend then xr_abuse.add_abuse(victim, 1) end end ---------------------------------------------------------------------------------------------------------------------- -- binder ---------------------------------------------------------------------------------------------------------------------- function setup_generic_scheme(npc,ini,scheme,section,stype,temp) local meet_section = ini:r_string_ex(section,"meet") local st = xr_logic.assign_storage_and_bind(npc,ini,"meet",meet_section,temp) end function add_to_binder(npc,char_ini,scheme,section,st,temp) if not npc then return end local manager = npc:motivation_action_manager() if not manager then return end local wp = world_property local evaluator = evaluator_contact("meet_contact", st) temp.action = action_meet_wait(npc:name(),"action_process_meet", st, char_ini) if not evaluator or not temp.action then return end manager:add_evaluator(xr_evaluators_id.stohe_meet_base + 1, evaluator) temp.action:add_precondition(wp(stalker_ids.property_alive,true)) temp.action:add_precondition(wp(stalker_ids.property_enemy,false)) temp.action:add_precondition(wp(stalker_ids.property_danger,false)) temp.action:add_precondition(wp(xr_evaluators_id.stohe_meet_base + 1,true)) temp.action:add_effect(wp(xr_evaluators_id.stohe_meet_base + 1,false)) manager:add_action(xr_actions_id.stohe_meet_base + 1, temp.action) st.meet_manager = Cmeet_manager(npc,st) xr_logic.subscribe_action_for_events(npc,st,st.meet_manager) end function configure_actions(npc,ini,scheme,section,stype,temp) if not npc then return end local manager = npc:motivation_action_manager() if not manager or not temp.action then return end local wp = world_property --printf("ACTION_ALIFE_ID(xr_meet.configure_actions): " .. tostring(xr_actions_id.alife)) local action = manager:action(xr_actions_id.alife) if action then action:add_precondition(wp(xr_evaluators_id.stohe_meet_base + 1, false)) end action = manager:action(xr_actions_id.state_mgr + 2) if action then action:add_precondition(wp(xr_evaluators_id.stohe_meet_base + 1, false)) end temp.action:add_precondition(wp(xr_evaluators_id.sidor_wounded_base,false)) temp.action:add_precondition(wp(xr_evaluators_id.abuse_base,false)) end function reset_generic_scheme(npc,scheme,section,stype,st) if (st.meet) then local meet_section if scheme == nil or scheme == "nil" then meet_section = st.ini:r_string_ex(st.section_logic,"meet") or "nil" else meet_section = st.ini:r_string_ex(section,"meet") or "nil" end init_meet(npc, st.ini, meet_section, st.meet, scheme) end end function disable_generic_scheme(npc,scheme,stype) db.storage[npc:id()].actor_dialogs = nil db.storage[npc:id()].actor_disable = nil end local default_meet = {} -- no sense to recreate for each npc -- Функция чтения настроек. В нее передается секция, откуда их нужно читать. function init_meet(npc, ini, section, st, scheme) --printf("MEET SECTION [%s][%s][%s]", tostring(st.meet_section), tostring(section), tostring(scheme)) if (section == st.meet_section and section ~= "nil") then return end st.meet_section = section -- TODO: fix the fucked up relations local comm_actor = character_community(db.actor):sub(7) local comm_npc = character_community(npc) local relation_enemy_1 = game_relations.is_factions_enemies( comm_actor , comm_npc ) local relation_enemy_2 = game_relations.get_npcs_relation(npc, db.actor) == game_object.enemy local is_enemy = (relation_enemy_1 or relation_enemy_2) and true or false if not (default_meet[is_enemy]) then default_meet[is_enemy] = {} end ------------------------------------- --local relation = game_relations.get_npcs_relation(npc, db.actor) if (is_enemy) then default_meet[is_enemy].close_distance = "0" default_meet[is_enemy].close_anim = "nil" default_meet[is_enemy].close_snd_distance = "0" default_meet[is_enemy].close_snd_hello = "nil" default_meet[is_enemy].close_snd_bye = "nil" default_meet[is_enemy].close_victim = "nil" default_meet[is_enemy].far_distance = "0" default_meet[is_enemy].far_anim = "nil" default_meet[is_enemy].far_snd_distance = "0" default_meet[is_enemy].far_snd = "nil" default_meet[is_enemy].far_victim = "nil" default_meet[is_enemy].snd_on_use = "nil" default_meet[is_enemy].use = "false" default_meet[is_enemy].meet_dialog = "nil" default_meet[is_enemy].abuse = "false" default_meet[is_enemy].trade_enable = "false" default_meet[is_enemy].allow_break = "true" default_meet[is_enemy].meet_on_talking = "true" default_meet[is_enemy].use_text = "nil" else default_meet[is_enemy].close_distance = "{=is_wounded} 0, {!is_squad_commander} 0, {!after_first_meet !actor_friend !actor_is_safemode =actor_has_weapon} 3, 2" default_meet[is_enemy].close_anim = "{=is_wounded} nil, {!is_squad_commander} nil, {!actor_is_safemode =actor_has_weapon} nil, talk_default" default_meet[is_enemy].close_snd_distance = "{=is_wounded} 0, {!is_squad_commander} 0, 3" default_meet[is_enemy].close_snd_hello = "{=is_wounded} nil, {!is_squad_commander} nil, {=actor_enemy} nil, {!after_first_meet !actor_friend !actor_is_safemode =actor_has_weapon} meet_stop, meet_hello" default_meet[is_enemy].close_snd_bye = "nil" default_meet[is_enemy].close_victim = "{=is_wounded} nil, {!is_squad_commander} nil, actor" default_meet[is_enemy].far_distance = "{=is_wounded} 0, {!is_squad_commander} 0, {!after_first_meet !actor_friend !actor_is_safemode =actor_has_weapon} 5, 3" default_meet[is_enemy].far_anim = "{=is_wounded} nil, {!is_squad_commander} nil, {!after_first_meet !actor_friend !actor_is_safemode =actor_has_weapon} threat_na, nil" default_meet[is_enemy].far_snd_distance = "{=is_wounded} 0, {!is_squad_commander} 0, 5" default_meet[is_enemy].far_snd = "{=is_wounded} nil, {!is_squad_commander} nil, {=actor_enemy} nil, {=is_story} nil, {!after_first_meet !actor_friend !actor_is_safemode =actor_has_weapon} meet_hide_weapon, meet_wait" default_meet[is_enemy].far_victim = "{=is_wounded} nil, {!is_squad_commander} nil, actor" default_meet[is_enemy].snd_on_use = "{=is_wounded} nil, {!is_squad_commander} meet_use_no_talk_leader, {=actor_enemy} nil, {=has_enemy} meet_use_no_fight, {!dist_to_actor_le(3)} nil" default_meet[is_enemy].use = "{=is_wounded} false, {!is_squad_commander} false, {=actor_enemy} false, {=has_enemy} false, {=dist_to_actor_le(3)} true, false" default_meet[is_enemy].meet_dialog = "nil" default_meet[is_enemy].abuse = "{=has_enemy} false, true" default_meet[is_enemy].trade_enable = "true" default_meet[is_enemy].allow_break = "true" default_meet[is_enemy].meet_on_talking = "true" default_meet[is_enemy].use_text = "nil" end local def = default_meet[is_enemy] if tostring(section) == "no_meet" then st.close_distance = xr_logic.parse_condlist(npc, section, "close_distance", "0") st.close_anim = xr_logic.parse_condlist(npc, section, "close_anim", "nil") st.close_snd_distance=xr_logic.parse_condlist(npc, section, "close_distance", "0") st.close_snd_hello = xr_logic.parse_condlist(npc, section, "close_snd_hello", "nil") st.close_snd_bye = xr_logic.parse_condlist(npc, section, "close_snd_bye", "nil") st.close_victim = xr_logic.parse_condlist(npc, section, "close_victim", "nil") st.far_distance = xr_logic.parse_condlist(npc, section, "far_distance", "0") st.far_anim = xr_logic.parse_condlist(npc, section, "far_anim", "nil") st.far_snd_distance = xr_logic.parse_condlist(npc, section, "far_distance", "0") st.far_snd = xr_logic.parse_condlist(npc, section, "far_snd", "nil") st.far_victim = xr_logic.parse_condlist(npc, section, "far_victim", "nil") st.snd_on_use = xr_logic.parse_condlist(npc, section, "snd_on_use", "nil") st.use = xr_logic.parse_condlist(npc, section, "use", "false") st.meet_dialog = xr_logic.parse_condlist(npc, section, "meet_dialog", "nil") st.abuse = xr_logic.parse_condlist(npc, section, "abuse", "false") st.trade_enable = xr_logic.parse_condlist(npc, section, "trade_enable", "true") st.allow_break = xr_logic.parse_condlist(npc, section, "allow_break", "true") st.meet_on_talking = xr_logic.parse_condlist(npc, section, "meet_on_talking", "false") st.use_text = xr_logic.parse_condlist(npc, section, "use_text", "nil") st.reset_distance = 30 st.meet_only_at_path = true else st.close_distance = ini:r_string_to_condlist(section,"close_distance",def.close_distance) st.close_anim = ini:r_string_to_condlist(section,"close_anim",def.close_anim) st.close_snd_distance=ini:r_string_to_condlist(section,"close_snd_distance",def.close_snd_distance) st.close_snd_hello = ini:r_string_to_condlist(section,"close_snd_hello",def.close_snd_hello) st.close_snd_bye = ini:r_string_to_condlist(section,"close_snd_bye",def.close_snd_bye) st.close_victim = ini:r_string_to_condlist(section,"close_victim",def.close_victim) st.far_distance = ini:r_string_to_condlist(section,"far_distance",def.far_distance) st.far_anim = ini:r_string_to_condlist(section,"far_anim",def.far_anim) st.far_snd_distance = ini:r_string_to_condlist(section,"far_snd_distance",def.far_snd_distance) st.far_snd = ini:r_string_to_condlist(section,"far_snd",def.far_snd) st.far_victim = ini:r_string_to_condlist(section,"far_victim",def.far_victim) st.snd_on_use = ini:r_string_to_condlist(section,"snd_on_use",def.snd_on_use) st.use = ini:r_string_to_condlist(section,"use",def.use) st.meet_dialog = ini:r_string_to_condlist(section,"meet_dialog",def.meet_dialog) st.abuse = ini:r_string_to_condlist(section,"abuse",def.abuse) st.trade_enable = ini:r_string_to_condlist(section,"trade_enable",def.trade_enable) st.allow_break = ini:r_string_to_condlist(section,"allow_break",def.allow_break) st.meet_on_talking = ini:r_string_to_condlist(section,"meet_on_talking",def.meet_on_talking) st.use_text = ini:r_string_to_condlist(section,"use_text",def.use_text) st.reset_distance = 30 st.meet_only_at_path = true end st.meet_manager:set_start_distance() --print_table(st.far_distance) -- флажок, что функция хотя бы раз вызывалась st.can_gtfo = ini:r_string_ex(section,"can_gtfo","true") st.meet_set = true end --- Находится ли чувак в данный момент в состоянии мита function is_meet(npc) local manager = npc:motivation_action_manager() if manager and manager:initialized() then local id = manager:current_action_id() if id == xr_actions_id.stohe_meet_base + 1 then return true end end return false end function process_npc_usability(npc) if (character_community(npc) == "zombied") then npc:disable_talk() return end if (IsWounded(npc)) then local st = db.storage[npc:id()] if (npc:relation(db.actor) >= game_object.enemy and st and st.victim_surrender ~= AC_ID) then npc:disable_talk() else local wounded = db.storage[npc:id()].wounded if wounded.enable_talk then npc:enable_talk() else npc:disable_talk() end end return end -- Special case for doc to force him to talk if (npc:section() == "mar_smart_terrain_doc_doctor") then npc:enable_talk() return end local meet = db.storage[npc:id()].meet if not (meet) then return end local use = meet.meet_manager.use if (use == "true") then if xr_corpse_detection.is_under_corpse_detection(npc) or xr_help_wounded.is_under_help_wounded(npc) then npc:disable_talk() else npc:enable_talk() end return end -- check if a task giver then force allow talk local id = npc:id() local task_info = task_manager.get_task_manager().task_info for k,v in pairs(task_info) do if (v.task_giver_id and v.task_giver_id == id) then npc:enable_talk() return -- check if it's the delivery dude elseif tasks_delivery.is_delivery_task(k) then local var = load_var(db.actor, k) if var and var.target_id and (var.target_id == id) then npc:enable_talk() return end end end if (use == "false") then npc:disable_talk() if npc:is_talking() then npc:stop_talk() end end end function on_game_start() RegisterScriptCallback("save_state",save_state) RegisterScriptCallback("load_state",load_state) end function save_state(m) for id,v in pairs(M) do local se = alife_object(id) if not (se and se:name() == v.name) then M[id] = nil end end m.dialog_override = M end function load_state(m) M = m.dialog_override or {} end function override_dialog(npc_id, dialog_name) local se = npc_id and alife_object(npc_id) if se and IsStalker(se) then M[npc_id] = { dialog_name = dialog_name, name = se:name() } else printf('%s (%s) is not a stalker', se and se.id, se and se:name()) return false end end function restore_dialog(npc_id) M[npc_id] = nil end function has_dialog_override(npc_id) return M[npc_id] and true end